package Modele;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
/**
 *
 * @author aminemekki
 */
public class WriterDataSet 
{

	/**
	 * Cree des exemples de difficultes croissante
	 * @param fichier
	 * @param level
	 * @param dim
	 * @param nb_exemple
	 * @throws IOException
	 */
	public static void writeForm(String fichier, int level, int dim, int nb_exemple) throws IOException
	{	
		File fichierExp = new File(fichier);

		for(int i = 0; i < nb_exemple; i++)
		{
			int type = (int) (Math.random() * 3 + 1);
			switch(type)
			{
			case 1 : writeRect(fichierExp,level, dim); break;
			case 2 : writeCircle(fichierExp,level,dim); break;
			case 3 : writeTriangle(fichierExp,level,dim);break;
			default : break;
			}
		}
	}

	/**
	 * Genere des cercles de difficultes croissante
	 * @param fichier
	 * @param level
	 * @param size
	 * @throws IOException
	 */
	private static void writeCircle(File fichier, int level, int size) throws IOException 
	{
		switch(level)
		{
		case 1 : 
			Cercle(fichier,size, (int)(size/2),(int)(size/2),13); 
			break;
		case 3 : 
			Cercle(fichier,size, (int)(size/2),(int)(size/2),(int)(Math.random() * 15) + 1); 
			break;
		case 2 : 
			int x = (int)(size/2);
			int y = (int)(size/ ((int)(Math.random() * 4) + 2));
			int r = (int)(Math.random() * 15) + 1;
			if(x + r > size)
				x = size - r;
			if(x - r < 0)
				x = r;
			if(y + r > size)
				y = size - r;
			if(y - r < 0)
				y = r;
			Cercle(fichier,size, x,y,r); 
			break;
		default : break;
		}
	}

	/**
	 * Genere des traingels de difficultes croissante
	 * @param fichier
	 * @param level
	 * @param size
	 * @throws IOException
	 */
	private static void writeTriangle(File fichier, int level, int size) throws IOException 
	{
		switch(level)
		{
		case 1 : 
			Triangle(fichier,size, (int)(size/2), (int)(size/2), 6, 0);
			break;
		case 3 : 
			Triangle(fichier,size, (int)(size/2) - 4, (int)(size/2), 6, -45);
			break;
		case 2 :
			int x = (int)(size/2) - 4;
			int y = (int)(size/2);
			int h = (int)(Math.random() * 6) + 1;
			Triangle(fichier,size, x, y, h, 45);
			break;
		default : break;
		}
	}

	/**
	 * Genere des Rectangles ou Carres de difficultes croissante
	 * @param fichier
	 * @param level
	 * @param size
	 * @throws IOException
	 */
	private static void writeRect(File fichier, int level, int size) throws IOException
	{
		switch(level)
		{
		case 1 : Rect(fichier, size, (int)(size/8),(int)(size/8),(int)(size/2),(int)(size/2));break;
		case 3 : Rect(fichier, size, (int)(size/(Math.random() * 8 + 1)),(int)(size/(Math.random() * 8 + 1)),(int)(size/2),(int)(size/2));break;
		case 2 : Rect(fichier, size, (int)(size/8),(int)(size/8),(int)(size/(Math.random() * 8 + 1)),(int)(size/(Math.random() * 8 + 1)));break;
		case 4 : Rect(fichier, size, (int)(size/(Math.random() * 8 + 1)),(int)(size/(Math.random() * 8 + 1)),(int)(size/(Math.random() * 8 + 1)),(int)(size/(Math.random() * 8 + 1)));break;
		case 5 : Rect2(fichier, size, (int)(size/8),(int)(size/8),(int)(size/2),(int)(size/2),45);break;
		case 6 : Rect2(fichier, size, (int)(size/8),(int)(size/8),(int)(size/(Math.random() * 8 + 1)),(int)(size/(Math.random() * 8 + 1)),45);break;
		default : break;
		}

	}

	/**
	 * Genere des Rectangles ou des Carres si w = h
	 * @param fichier
	 * @param size
	 * @param x
	 * @param y
	 * @param w
	 * @param h
	 * @throws IOException
	 */
	private static void Rect(File fichier, int size, int x, int y, int w, int h) throws IOException 
	{
		FileWriter f = new FileWriter(fichier,true);
		f.write("1 ");
		double [][] tab = new double[size][size];
		for(int i = 0; i < tab.length; i++)
		{
			for(int j = 0; j < tab[i].length; j++)
			{
				if((i >= x && i <= (x + h)) && (j >= y && j <= (y + w) ) )
				{
					f.write( ((i * size) + (j + 1)) + ":0.71 ");
				}
			}
		}
		f.write("\n");
		f.close();
	}

	/**
	 * Genere un rectangle ou un carre puis lui applique une rotation
	 * @param fichier
	 * @param size
	 * @param x
	 * @param y
	 * @param w
	 * @param h
	 * @param rotation
	 * @throws IOException
	 */
	private static void Rect2(File fichier, int size, int x, int y, int w, int h, double rotation) throws IOException 
	{
		FileWriter f = new FileWriter(fichier,true);
		f.write("1 ");
		int [][] tab = new int[size][size];
		int [][] tab2;
		for(int i = 0; i < tab.length; i++)
		{
			for(int j = 0; j < tab[i].length; j++)
			{
				if((i >= x && i <= (x + h)) && (j >= y && j <= (y + w) ) )
				{
					tab[i][j] = 22;
				}
				else
				{
					tab[i][j] = 11;
				}
			}
		}

		tab2 = rotate(size,tab,rotation);

		for (int i = 0; i < size; i++) {
			for (int j = 0; j < size; j++)
			{
				if(tab2[i][j] == 22)
				{
					f.write(((i  * size) + (j + 1)) + ":0.71 ");
				}
			}
		}
		
		f.write("\n");
		f.close();
	}

	/**
	 * Genere des triangles selon l'orientation
	 * @param fichier
	 * @param size
	 * @param x
	 * @param y
	 * @param l
	 * @param rotation
	 * @throws IOException
	 */
	private static void Triangle(File fichier, int size, int x, int y, int l, double rotation) throws IOException 
	{
		FileWriter f = new FileWriter(fichier,true);
		f.write("3 ");
		int [][] tab = new int[size][size];
		int [][] tab2;
		int l_temp = l;
		for(int i = 0; i < size; i++)
		{
			for(int j = 0; j < size; j++)
			{
				if((i >= x) && (j >= (y - l_temp)) && (j <= (y + l_temp)))
				{
					tab[i][j] = 22;
				}
				else
				{
					tab[i][j] = 11;
				}
			}
			if(i >= x)
				l_temp--;
		}

		tab2 = rotate(size,tab,rotation);

		for (int i = 0; i < size; i++) {
			for (int j = 0; j < size; j++)
			{
				if(tab2[i][j] == 22)
				{
					f.write(((i  * size) + (j + 1)) + ":0.71 ");
				}
			}
		}
		f.write("\n");
		f.close();
	}

	/**
	 * Genere des cercles et des ellipses
	 * @param fichier
	 * @param size
	 * @param x
	 * @param y
	 * @param r
	 * @throws IOException
	 */
	private static void Cercle(File fichier, int size, int x, int y, int r) throws IOException 
	{
		FileWriter f = new FileWriter(fichier,true);
		f.write("2 ");
		for(int i = 0; i < size; i++)
		{
			for(int j = 0; j < size; j++)
			{
				if( Math.sqrt(Math.pow(i - x, 2) + Math.pow(j - y, 2)) < r )
				{
					f.write(((i  * size) + (j + 1)) + ":0.71 ");
				}
			}
		}
		f.write("\n");
		f.close();
	}

	/**
	 * Seconde facon de generer des triangles
	 * @param n
	 * @param x1
	 * @param y1
	 * @param x2
	 * @param y2
	 * @param x3
	 * @param y3
	 * @return
	 */
	public static int[][] Triangle(int n, int x1, int y1, int x2, int y2, int x3, int y3) {

		int[][] matrix = new int[n][n];
		
		for(int i = 0; i < n ; i++) {
		
			for(int j = 0; j < n ; j++) {
				double n1 = Math.sqrt( ( x1 - j )*( x1 - j ) + ( y1 - i )*( y1 - i ) );
				double v1x = ( (double)( x1 - j ) ) / n1;
				double v1y = ( (double)( y1 - i ) ) / n1;
				double n2 = Math.sqrt( ( x2 - j )*( x2 - j ) + ( y2 - i )*( y2 - i) );
				double v2x = ( (double)( x2 - j ) ) / n2;
				double v2y = ( (double)( y2 - i ) ) / n2;
				double n3 = Math.sqrt( ( x3 - j )*( x3 - j ) + ( y3 - i )*( y3 - i ) );
				double v3x = ( (double)( x3 - j ) ) / n3;
				double v3y = ( (double)( y3 - i ) ) / n3;
				
				double sum_x = v1x + v2x + v3x; 
				double sum_y = v1y + v2y + v3y;
				
				double norm = sum_x*sum_x + sum_y*sum_y;
				
				if ( norm > 1 ) {
					matrix[i][j] = 0;
				} else {
					matrix[i][j] = 1;
				}
			}

		}
		
		return matrix;
	}
	
	/**
	 * Effectue une rotation du tableau passe en argument
	 * @param size
	 * @param tab
	 * @param rotation
	 * @return
	 */
	private static int[][] rotate(int size, int[][] tab, double rotation)
	{
		int [][] tab2 = new int[size][size];
		double angle = Math.toRadians(rotation);//Math.toRadians(Double.parseDouble(args[1]));
		double sin = Math.sin(angle);
		double cos = Math.cos(angle);
		double i0 = 0.5 * ((int)(size / 2)  - 1);     // point to rotate about
		double j0 = 0.5 * ((int)(size / 2) - 1);     // center of image
		//Picture pic2 = new Picture(width, height);

		// rotation
		for (int i = 0; i < size; i++) {
			for (int j = 0; j < size; j++) {
				double a = i - i0;
				double b = j - j0;
				int ii = (int) (+a * cos - b * sin + i0);
				int jj = (int) (+a * sin + b * cos + j0);

				// plot pixel (i, j) the same color as (ii, jj) if it's in bounds
				if (ii >= 0 && ii < size && jj >= 0 && jj < size) {
					tab2[i][j] = tab[ii][jj];
				}
				else
				{
					tab2[i][j] = 11;
				}
			}
		}
		return tab2;
	}
	
}
